#define _GNU_SOURCE     //在源文件开头定义_GNU_SOURCE宏
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <signal.h>
#include <termios.h> 
#include <sys/types.h>   
#include <sys/time.h>   
#include <sys/stat.h>   
#include <fcntl.h>   
#include <unistd.h>   
#include <errno.h>   
#include <stdlib.h>   
#include <string.h>   
#include <sys/ipc.h>
#include <sys/shm.h>
#include <linux/joystick.h>   
//#include <linux/list.h> /*郁闷，不能直接使用linux自带的list链表，需要单独提取出来，见前面的code*/   
#include "listop.h"   
#include "pid.h"


uint8_t uart_rx_buf[32];
/*LOG*/
#define LOG_DBG(fmt, ...)  fprintf(stdout, fmt, ##__VA_ARGS__)
#define LOG_ERR(fmt, ...)  fprintf(stderr, fmt, ##__VA_ARGS__) 

/*uart*/
void uart_init(int fd){
    struct termios old_cfg;
    if(0>tcgetattr(fd,&old_cfg))
    {
	    LOG_ERR("uart connection error\n");
	    return ;
    }

    struct termios new_cfg;

    memset(&new_cfg,0x0,sizeof(struct termios));

    //配置为原始模式
    cfmakeraw(&new_cfg);

    //使能接收
    new_cfg.c_cflag |= CREAD;

    //设置波特率
    cfsetspeed(&new_cfg,B115200);

    //设置数据位大小
    new_cfg.c_cflag &= ~CSIZE;
    new_cfg.c_cflag |= CS8;//数据位为8位

    //设置奇偶校验


    //奇校验使能
    new_cfg.c_cflag |= (PARODD | PARENB);
    new_cfg.c_iflag |= INPCK;
    //偶校验使能
    new_cfg.c_cflag |= PARENB;
    new_cfg.c_cflag &= ~PARODD; /* 清除 PARODD 标志，配置为偶校验 */
    new_cfg.c_iflag |= INPCK;
    //无校验
    new_cfg.c_cflag &= ~PARENB;
    new_cfg.c_iflag &= ~INPCK;

    //设置停止位
    // 将停止位设置为一个比特
    new_cfg.c_cflag &= ~CSTOPB;
    // 将停止位设置为 2 个比特
    new_cfg.c_cflag |= CSTOPB;

    //设置MIN和TIME的值
    new_cfg.c_cc[VTIME] = 0;
    new_cfg.c_cc[VMIN] = 0;
    
    //调用tcflush（）清空缓冲区
    tcflush(fd, TCIOFLUSH);
    
    //调用tcsetattr()将配置写入设备，使其立即生效
    tcsetattr(fd,TCSANOW,&new_cfg);

}

/*接收数据*/
void *receive_data()
{
    int uartfd = *(int *)arg;
    Dev_Sta_Data dev_sta_data;
    Report_Exc report_exec;
    uint8_t *data_buf =  (uint8_t *) &dev_sta_data;
    uint32_t count = 0;
    bool get_frame_flag = false;
    time_t t;
    struct tm  *timenow;
    FILE  *file_fd = NULL;
    char outfile[128];
    key_t record_key , report_key;                                        
    int shm_id_record,shm_id_report;                                      
    char *record_buf ,*report_buf;
    //获取key                                      
    if((record_key = ftok("/home/linjunhan/dolphin/record_data",0xf)) < 0)                    
         perror("ftok");                                                                 
     //创建或获取共享内存                               
    if((shm_id_record = shmget(record_key,SHMSIZE,IPC_CREAT|0666)) < 0)
         perror("shmget");                                                                                                 
     //映射共享内存到进程的虚拟空间                        
    if((record_buf = shmat(shm_id_record,NULL,0)) < 0)                   
         perror("shmat");                                            

    //获取key                                      
    if((report_key = ftok("/home/linjunhan/dolphin/report",0xe)) < 0)                    
         perror("ftok");                                                                 
     //创建或获取共享内存                               
    if((shm_id_report = shmget(report_key,SHMSIZE,IPC_CREAT|0666)) < 0)
         perror("shmget");                                                                                                 
     //映射共享内存到进程的虚拟空间                        
    if((report_buf = shmat(shm_id_report,NULL,0)) < 0)                   
         perror("shmat");                   

    t = time(NULL);  

    while(1)
    {
        ret=read(uartfd,uart_rx_buf,32);
        if(ret != 0){        
            if(uart_rx_buf[0] == NANO_FRAME_HEAD_LOW && uart_rx_buf[1] == NANO_FRAME_HEAD_HIGH ){
                get_frame_flag = true;
                count = 0;
            }
            if(get_frame_flag){
                for(int i = 0; i < 32; ++i){
                    *(data_buf + i + 32*count) = uart_rx_buf[i];
                }
                count++;
                if(count*32 > DEV_FRAME_LEN){
                    printf("%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.2f, %.2f, %.2f\n",dev_sta_data.sensor_sta.imu0.SAngle[0],dev_sta_data.sensor_sta.imu0.SAngle[1], dev_sta_data.sensor_sta.imu0.SAngle[2],dev_sta_data.sensor_sta.imu0.SGyro[0],dev_sta_data.sensor_sta.imu0.SGyro[1], dev_sta_data.sensor_sta.imu0.SGyro[2],dev_sta_data.sensor_sta.imu0.SAcc[0],dev_sta_data.sensor_sta.imu0.SAcc[1], dev_sta_data.sensor_sta.imu0.SAcc[2],dev_sta_data.sensor_sta.imu1.SAngle[0],dev_sta_data.sensor_sta.imu1.SAngle[1], dev_sta_data.sensor_sta.imu1.SAngle[2],dev_sta_data.sensor_sta.imu1.SGyro[0],dev_sta_data.sensor_sta.imu1.SGyro[1], dev_sta_data.sensor_sta.imu1.SGyro[2],dev_sta_data.sensor_sta.imu1.SAcc[0],dev_sta_data.sensor_sta.imu1.SAcc[1], dev_sta_data.sensor_sta.imu1.SAcc[2],dev_sta_data.motor_sta.motor_spd,dev_sta_data.motor_sta.motor_curr,dev_sta_data.motor_sta.motor_vol);
                    
                    if(dev_sta_data.sensor_sta.leak){
                        report_exec.leak = 1;
                        //printf("leak detected is: %d\n",dev_sta_data.sensor_sta.leak);
                    }
                    else{
                        report_exec.leak = 0;
                    }
                        
                    if(dev_sta_data.sensor_sta.battery.elec < 30){
                        //printf("battery elec is less than 30\n");
                        report_exec.elec = 1;
                    }
                    else{
                        report_exec.elec = 0;
                    }
                    get_frame_flag = false;
                }
            }
        }

    }
}

void control_init()
{
    float error, lastError, integral, derivative, controlSignal;

}

int main()
{

}